#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <assert.h>
#define NUM 1024
#define OPT_NUM 64
char LineCommand[NUM];
char *myargv[OPT_NUM];
int LastCode=0;
int LastSig=0;
int status=0;
int main()
{
 while(1)
 {  //输出提示符
  printf("用户名@主机名 当前路径# ");
  fflush(stdout);
  
  //获取用户输入
  char* s=fgets(LineCommand,sizeof(LineCommand)-1,stdin);
  assert(s!=NULL);
  LineCommand[strlen(LineCommand)-1]=0;
//  printf("test : %s\n",LineCommand);
  //字符串切割
  myargv[0]=strtok(LineCommand," ");
  int i=1;
  if(myargv[0]!=NULL && strcmp(myargv[0],"ls")==0)
  {
    myargv[i++]=(char*)"--color=auto";
  }
  //如果没有字串 strtok->NULL
  while(myargv[i++]=strtok(NULL," "));
  //如果是cd命令，我们不需要创建子进程，让shell自己执行对应的命令，本质就是执行系统接口
  //像这种不需要子进程来执行，而是shell自己执行的命令我们称之为内置命令
  if(myargv[0]!=NULL && strcmp(myargv[0],"cd")==0)
  {
    if(myargv[1]!=NULL)chdir(myargv[1]);
    continue;
  }
  if(myargv[0]!=NULL && myargv[1]!=NULL)
  {
    if(strcmp(myargv[0],"echo")==0 && strcmp(myargv[1],"$?")==0)
    {
      printf("%d %d\n",LastCode,LastSig);
    }
    else 
    {
      printf("%s\n",myargv[1]);
    }
    continue;
  }
#ifdef DEBUG
 for(int i=0;myargv[i];++i)
  {
    printf("myargv[%d] : %s\n",i,myargv[i]);
  }
#endif 
 //执行命令
 pid_t id=fork();
 assert(id!=-1);
 if(id==0)
 {
  execvp(myargv[0],myargv);
  exit(1);
 }
 pid_t ret=waitpid(id,&status,0);
 LastCode=((status>>8) & 0xff);
 LastSig= status & 0x7f;
 assert(ret>0);
(void)ret;
  }
}
